Copyright (c) 1995, 1996, 1997 by John Montbriand. All Rights Reserved.
Permission granted for public use.
Distribute freely in areas where the laws of copyright apply.
USE AT YOUR OWN RISK.
DO NOT DISTRIBUTE MODIFIED COPIES.
Comments/questions/postcards* to the author at the address:
John Montbriand
P.O. Box. 1133
Saskatoon Saskatchewan Canada
S7K 3N2
or by email at:
tinyjohn@sk.sympatico.ca
*if you mail a postcard, then I will provide you with technical support regarding questions you may have about this file.
About BinHex decoder/encoder routines...
These routines implement BinHex encoding and decoding in a input/output source/destination independent way. Complete source code is provided along with a MPW tool example. Usable in System 6 on up... Can handle any file size. Uses a chained read/write algorithm so memory requirements are low.
Sections found below
Input and Output
A Data Sink
EXAMPLE
A Data Source
EXAMPLE
SPECIAL NOTE ABOUT DECODING DATA
Naming Decoded Files
EXAMPLE
Encoding BinHex Files
EXAMPLE
Decoding BinHex Files
EXAMPLE
Multi-part files
Files in this package
Copies for Sale!
NO WARRANTY
Bug reports make this a better product!
Other
Input and Output
Input and Output are handled by callback routines that you provide. In your callbacks it is your responsibility to either retrieve data or store the data. Callbacks you provide are as follows:
A Data Sink
This routine accepts data produced by the BinHex encoder. If you are only interested in Encoding BinHex files, then this is the only routine you have to implement. It is declared as:
typedef OSErr (*HQXSink)(void* buffer, long count, long refcon);
• buffer is a pointer to the BinHex data.
• count is the number of bytes in the data buffer.
• refcon is same as the refcon parameter passed to the HQXEncode routine.
HQXSink defines a function that will receive data produced by the HQXEncode routine. refcon is available for your application's use and is the same refcon value passed to HQXEncode. returning any error code other than noErr will abort HQXEncode. HQXEncode implements a buffering scheme of its own, so there is no need for your sink function to be concerned about buffering data.
EXAMPLE: Here's an example using an open Macintosh file:
short gFileRefNum ; /* an open Macintosh file */
OSErr MySink(void* buffer, long count, long refcon) {
return FSWrite(gFileRefNum, &count, buffer);
}
A Data Source
This routine is called by the Decoder function whenever it requires more BinHex data during the decoding process. If you are only interested in Decoding BinHex files, then this is the only routine you have to implement. It is declared as:
typedef OSErr (*HQXSource)(void* buffer, long *count, long refcon);
• buffer is a pointer a buffer that has been prepared to received.
• *count is the number of bytes being requested. Before returning, your source function should set *count to the number of bytes actually read into the data buffer (any value larger than zero is will continue processing. a value of zero will abort processing).
• refcon is same as the refcon parameter passed to the HQXEncode routine.
HQXSource defines a function providing a data source for the HQXDecode routine. Your function should attempt to read *count bytes to the buffer. Before returning, your function should set *count to the actual number of bytes read into the buffer. If count is zero, or the source function returns some result other than eofErr, HQXDecode aborts processing. HQXDecode implements its own buffering scheme so your source function need not be concerned about buffering.
EXAMPLE: Here's an example using an open Macintosh file:
short gFileRefNum; /* an open Macintosh file */
OSErr MySource(void* buffer, long *count, long refcon) {
return FSRead(gFileRefNum, count, buffer);
}
SPECIAL NOTE ABOUT DECODING DATA: Only BinHex characters delimited by colons are converted and multiple BinHex data sections are allowed. For example, the data sequence:
In other words, colons in the input stream can be used to toggle BinHex decoding on and off.
Naming Decoded Files
The name of the produced file is determined from the BinHex data during the first part of the decoding process. By default, a file with this name is created in the current directory. If you would like to override this behavior, then you can provide an optional name filter function allowing you to modify the name and location of the decoded file. This function is declared as:
typedef OSErr (*HQXNameFilter)(StringPtr name, short *vol, long *dir, long refcon);
• name, is the name of the file extracted from the BinHex information.
• *vol and *dir are initially set to zero, but can be modified to refer to any valid directory.
• refcon is same as the refcon parameter passed to the HQXDecode routine.
HQXNameFilter is an optional routine allowing your application opportunity to modify the file name and location of the macintosh file being decoded. If your filter function returns a non-zero result code, HQXDecode stops processing data from the source and returns the result code. when HQXNameFilter is called, name is the name of the file and *vol and *dir will be zero. Your routine can modify any or all of these parameters to specify a different output file location.
EXAMPLE: Here's an example using the Standard File package to place the file:
OSErr MyNameFilter(StringPtr name, short *vol, long *dir, long refcon) {
StandardFileReply reply;
StandardPutFile ("\pSave As:", name, &reply);
if (reply.sfGood) {
PLstrcpy(name, reply.sfFile.name);
*vol = reply.sfFile.vRefNum;
*dir = reply.sfFile.parID;
} else return userCanceledErr;
}
Encoding BinHex Files
The routine HQXEncode encodes a macintosh file in BinHex format sending the produced output to the data sink routine you provide as a parameter. This routine is defined as:
OSErr HQXEncode(StringPtr name, short vol, long dir, HQXSink dst, long refcon);
• name, vol, and dir refer to the macintosh file's disk location.
• dst is the destination data sink where encoded output is sent
• refcon is a parameter for your own use that is passed along to your sink function
HQXEncode reads the indicated macintosh file and outputs the BinHex equivalent to the sink. If the HQXSink returns a non-zero result code, then execution stops and HQXEncode will return the result. refcon is a value passed to the sink function. HQXEncode implements its own internal buffering scheme so your sink function need not be concerned about buffering data.
EXAMPLE: Here's an example of how to encode a file using the Standard File package and the MySink function defined above. The result is saved in a MPW text file:
EXAMPLE: Here's an example of how to encode a file using the standard file package and the MySink function defined above. The result is saved in a MPW text file:
Decoding BinHex Files
The routine HQXDecode decodes BinHex data retrieved via. your source function and produces a macintosh file. The routine is defined as follows:
• fname is the name filter function you provide. If you want the file to be created in the current directory using the name from the BinHex data, then this parameter may be set to NULL.
• if can_replace is true, then if a file already exists with the same name as the output file, it will be replaced.
• if header_search is true, then the decoder searches for the string "(This file must be converted with BinHex 4.0)" in the input stream and does not start processing BinHex data until it is found.
• refcon is a parameter for your own use that is passed along to your source function
HQXDecode decodes a BinHex file using data from the source function. fname, if not NULL, is called once the file name has been extracted from the BinHex data so you can change where the file is saved. if can_replace is true then decoded files will replace files with the same name. refcon is an application-specific parameter passed to both the name filter function and the source function. if header_search is true, the routine does a search for the string "(This file must be converted with BinHex 4.0)" before beginning decoding BinHex data.
EXAMPLE: Here's an example of how to decode a file using the Standard File package and both the MySource and the MyNameFilter functions defined above.
Obviously, since these routines are input independent, they do not have access multiple BinHex files during the decoding or encoding process. Handling of multi-part files is a feature you can easily build into your Sink and Source routines.
Files in this package
hqx.c -- source code for the BinHex routine's implementation
hqx.h -- header file providing interfaces to the BinHex routines
ReadMe -- this file
:example: -- MPW example Tool
:obj: -- object files made during compile
hqx.c -- the hqx library file
hqx.h -- the hqx library interface file
hqxtool -- a compiled version of the tool
hqxtool.c -- tool source code
hqxtool.r -- rez file for the tool
hqxtool.rsrc -- resource file for the tool
MakeFile -- make command file, builds the tool
:Libraries: -- precompiled libraries, ready to link. See :example:MakeFile for the compiler options used.
hqx.c.o -- 68K version of the hqx library
hqx.xcoff -- PowerPC version of the hqx library
Copies for Sale!
These libraries are provided for free and you may use them in any program you make; however, if you would like to purchase a copy of these libraries and have a legal paper-trail establishing your right to use them, then send along a cheque or a money order in the amount of $10.00 for the purchase of one copy and I'll send you a receipt.
NO WARRANTY
No warranties are made regarding these files. John Montbriand disclaims all warranties regarding these files, either express or implied, including but not limited to implied warranties of merchantability and fitness for any particular purpose. These files are provided "AS IS" without any warranty of any kind. Use them at your own risk. Copies of these files are not for sale in areas where the law does not allow exculsion of implied warranties.
Bug reports make this a better product!
As in all of my products, I advertise a $10.00 finder's fee for bug reports that lead to corrections. If you find a problem here, report it! it could be worth your while....